<template>
  <!--:view-id="gaibian"-->
  <div class="z-tree">
    <div class="z-tree-node" v-if="datas">
      <!-- (datas[childprops.lv])-->
      <div class="z-tree-content" v-on:click.stop="viewinfo?'':checkSelf(datas)" :style="{ 'padding-left': level * 16 + 'px' }" :class="{'active':onedefault == datas.id,'notallow':viewinfo}">
        <i class="z-tree-icon iconfont" :class="{'icon-tianjia':!datas.showChild,'icon-jianqu':datas.showChild}" v-if="datas[childprops.children]" v-on:click.stop="showChildren(datas)"></i>
        <i class="z-none" v-if="!datas[childprops.children]"></i> 
        <span v-if='!multiple' class="z-tree-node-text" :title="datas[childprops.name]">
          {{datas[childprops.name]}}
        </span>
        <div class="z-mulbox" v-else :style="{'max-width': '100%'}" :title="datas[childprops.name]">
          <div class="z-mask"></div>
          <el-checkbox class="z-check" :label="datas.id" v-model="curdefult">
            {{datas[childprops.name]}}
          </el-checkbox>
        </div>
      </div>
      <transition name="donghua" @before-enter="beforeEnter" @enter="Enter" @after-enter="afterEnter" @before-leave="beforeLeave" @leave="Leave" @after-leave="afterLeave">
       <div class="z-tree-node-children" v-show="datas.showChild">
          <!-- <div class="z-tree-node">  :style="{ 'padding-left': (datas.lv) * 16 + 'px' }" 
                    <div class="z-tree-content">
                        <span class="z-tree-icon">+</span>
                        <span class="z-tree-node-text">
                            2级1
                        </span>
                    </div>
                </div> -->
          <!--v-on:showid="changeShow" 默认展开选中项-->
          <z-tree :viewinfo="viewinfo" :checkass="checkass" :regchild="regchild" :allcheck="allcheck" v-for="item in datas[childprops.children]" :level="levels" :isexpand="isexpand" :key="item.id" :datas="item" :childprops="childprops" :showLv="showLv" :defaults="onedefault" :arrdefaults='curdefult' :multiple="multiple" v-on:asscheck="assCheck" v-on:curcheck="curCheck"></z-tree>
        </div>
      </transition>
    </div>
  </div>
</template>

<script>
const elTransition =
  "0.3s height ease-in-out, 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out";
export default {
  name: "zTree",
  props: {
    datas: {
      type: Object,
      defautl: {}
    },
    openlv: {
      type: String
    },
    showLv: {
      type: Number
    },
    defaults: {},
    arrdefaults: {
      type: Array
    },
    multiple: {
      type: Boolean
    },
    childprops: {
      type: Object
    },
    viewinfo: {
      type: Boolean,
      default: false
    },
    level: {
      type: Number,
      defaults: 1
    },
    isexpand: {
      type: Boolean
    },
    allcheck: {
      type: Boolean
    },
    checkass: {
      type: Boolean,
      default: false
    },
    regchild:{
      type:Boolean,
      default:false
    }
    // namearrs: {
    //   type: Array
    // }
  },
  data() {
    return {
      showChild: false,
      active: 0,
      curdefult: [],
      onedefault: "",
      namearrsto: [],
      newdata: {},
      assTrue: 0
    };
  },
  watch: {
    defaults(val) {
      this.curdefult = this.arrdefaults;
      this.onedefault = this.defaults;
      this.newdata = this.datas;
      this.dds();
    },
    arrdefaults(val) {
      this.curdefult = this.arrdefaults;
      this.onedefault = this.defaults;
      this.newdata = this.datas;
      this.dds();
    },
    onedefault() {
      this.curdefult = this.arrdefaults;
      this.onedefault = this.defaults;
      this.newdata = this.datas;
      this.dds();
    },
    isexpand(val) {
      let childprops = this.childprops;
      if (val) {
        this.$set(this.datas, childprops.showChild, true);
        this.$set(this.datas, 'showChild', true);
      } else {
        this.$set(this.datas,'showChild', false);
      }
    },
    allcheck(val) {
      if (val) {
        this.checkall(this.datas);
      } else {
        this.cancelall(this.datas);
      }
    }
  },
  computed: {
    gaibian() {
      this.curdefult = this.arrdefaults;
      this.onedefault = this.defaults;
      this.newdata = this.datas;
    },
    levels() {
      return this.level + 1;
    }
  },
  mounted() {
    let childprops = this.childprops;
    if (this.allcheck) {
      this.checkSelf(this.datas);
    }
    this.onedefault = this.defautls;
    if (this.isexpand) {
      if(this.regchild){
         if(!this.datas[childprops.showChild]){
          this.$set(this.datas, 'showChild', true);
        }else{
          this.$set(this.datas, 'showChild', false);
        }
      }else{ 
         this.$set(this.datas, 'showChild', true);
      }
    } else {
      this.$set(this.datas, 'showChild', false);
    }

    // this.dds()
  },

  methods: {
    beforeEnter(el) {
      el.style.transition = elTransition;
      if (!el.dataset) el.dataset = {};

      el.dataset.oldPaddingTop = el.style.paddingTop;
      el.dataset.oldPaddingBottom = el.style.paddingBottom;

      el.style.height = 0;
      el.style.paddingTop = 0;
      el.style.paddingBottom = 0;
    },
    Enter(el) {
      el.dataset.oldOverflow = el.style.overflow;
      if (el.scrollHeight !== 0) {
        el.style.height = el.scrollHeight + "px";
        el.style.paddingTop = el.dataset.oldPaddingTop;
        el.style.paddingBottom = el.dataset.oldPaddingBottom;
      } else {
        el.style.height = "";
        el.style.paddingTop = el.dataset.oldPaddingTop;
        el.style.paddingBottom = el.dataset.oldPaddingBottom;
      }

      el.style.overflow = "hidden";
    },
    afterEnter(el) {
      el.style.transition = "";
      el.style.height = "";
      el.style.overflow = el.dataset.oldOverflow;
    },
    beforeLeave(el) {
      if (!el.dataset) el.dataset = {};
      el.dataset.oldPaddingTop = el.style.paddingTop;
      el.dataset.oldPaddingBottom = el.style.paddingBottom;
      el.dataset.oldOverflow = el.style.overflow;

      el.style.height = el.scrollHeight + "px";
      el.style.overflow = "hidden";
    },
    Leave(el) {
      if (el.scrollHeight !== 0) {
        el.style.transition = elTransition;
        el.style.height = 0;
        el.style.paddingTop = 0;
        el.style.paddingBottom = 0;
      }
    },
    afterLeave(el) {
      el.style.transition = "";
      el.style.height = "";
      el.style.overflow = el.dataset.oldOverflow;
      el.style.paddingTop = el.dataset.oldPaddingTop;
      el.style.paddingBottom = el.dataset.oldPaddingBottom;
    },
    dds() {
      let childprops = this.childprops;
      if (this.datas) {
        //默认展开1级
        // if (this.datas[childprops.lv] == 1 || this.datas[childprops.lv] == 0) {
        //   this.$set(this.datas, "showChild", true);
        // }
        // //默认展开2级
        // if (this.datas[childprops.lv] == this.showLv) {
        //   this.$set(this.datas, "showChild", true);
        // }
        //默认展开全部

        //判断是多选还是单选
        if (this.multiple) {
          if (this.arrdefaults) {
            //判断
            let data = this.arrdefaults;
            this.curdefult = data;
            //this.changeShow(data);

            //把默认选中项的name抛出
            // this.namearrsto = this.namearrs;
            // let ischeck = data.findIndex(item => item == this.datas.id);
            // let isname = this.namearrsto.findIndex(
            //   item => item == this.datas[childprops.name]
            // );
            // if (ischeck !== -1 && isname !== -1) {
            //   //如果当前值在namearrs里存在
            //   let arr = this.namearrsto;
            //   //arr.push(this.datas[childprops.name]);
            //   this.namearrsto = arr;
            //   this.$emit("namearr", arr);
            // } else if (ischeck !== -1 && isname == -1) {
            //   let arr = this.namearrsto;
            //   arr.push(this.datas[childprops.name]);
            //   this.namearrsto = arr;
            //   this.$emit("namearr", arr);
            // }
          }
        } else {
          if (this.defaults == this.datas.id) {
            this.$emit("curcheck", this.datas);
          }
        }
      }
    },
    showChildren(item) {

      let level = this.level;
      let obj = this.datas;
      let childprops = this.childprops
      if (item.showChild) {
        this.$set(item, 'showChild', false);
        if (level == 1) {
          this.$emit("show", 1);
        }
      } else {
        this.$set(item, 'showChild', true);
        if (level == 1) {
          this.$emit("show", 2);
        }
      }
    },
    //点击选中
    checkSelf(val) {
      let childprops = this.childprops;
      if (this.multiple) {
        //如果是多选
        let arr = this.curdefult;
        let have = arr.findIndex(item => item == val.id);
        // let namearrs = this.namearrsto; //当前选中name的数组
        // let havename = namearrs.findIndex(item => item == val[childprops.name]);
        if (have !== -1) {
          //如果是已经选中的项 取消选择 在数组里删除对应的项
          arr.splice(have, 1);
          if (this.checkass) {
            console.log("走啊走啊");
            this.$emit("asscheck", 1);
          }
          if (val[childprops.children] instanceof Array) {
            //如果有子集 则把子集的项取消选择 在数组删除对应的项
            let haveid = this.maparr(val[childprops.children]); //获取所有子集的id

            haveid.map(function(obj, index) {
              //遍历 删除数组对应的id
              if (arr.findIndex(item => item == obj) !== -1) {
                arr.splice(arr.findIndex(item => item == obj), 1);
              }
            });
          }
        } else {
          //如果未选择项 选择并在数组内追加
          if (val[childprops.children] instanceof Array) {
            //如果children是数组 则把子集的项追加到数组
            let haveid = this.maparr(val[childprops.children]); //获取所有子集的id的数组
            haveid.unshift(val.id); //追加
            // this.deletSame(arr,haveid);

            for (let j = 0; j < haveid.length; j++) {
              for (let i = 0; i < arr.length; i++) {
                const element = arr[i];
                if (arr[i] == haveid[j]) {
                  arr.splice(i, 1);
                }
              }
            }
            arr = this.uq(arr, haveid); //合并数组
            //arr.unshift(val.id); //追加
          } else {
            arr.push(val.id); //追加
          }
          if (this.checkass) {
            this.$emit("asscheck", 2);
          }
        }

        this.curdefult = arr; //设定v-model的值为改变后数组
        this.$emit("curcheck", arr); //向上提交
      } else {
        this.onedefault = val.id;
        this.active = val.id;
        this.$emit("curcheck", val);
      }
    },
    assCheck(val) {
      this.assTrue = val;
    },
    //全选
    checkall(val) {
      let childprops = this.childprops;
      if (this.multiple) {
        //如果是多选
        let arr = this.curdefult;

        //如果是已经选中的项 取消选择 在数组里删除对应的项

        if (val[childprops.children] instanceof Array) {
          //如果children是数组 则把子集的项追加到数组
          let haveid = this.maparr(val[childprops.children]); //获取所有子集的id的数组
          haveid.unshift(val.id); //追加
          arr = this.uq(arr, haveid); //合并数组
          //arr.unshift(val.id); //追加
        } else {
          arr.push(val.id); //追加
        }

        this.curdefult = arr; //设定v-model的值为改变后数组
        this.$emit("curcheck", arr); //向上提交
      }
    },
    //全取消
    cancelall(val) {
      let childprops = this.childprops;
      let arr = this.curdefult;

      let have = arr.findIndex(item => item == val.id);
      //如果是已经选中的项 取消选择 在数组里删除对应的项
      arr.splice(have, 1);

      if (val[childprops.children] instanceof Array) {
        //如果有子集 则把子集的项取消选择 在数组删除对应的项
        let haveid = this.maparr(val[childprops.children]); //获取所有子集的id

        haveid.map(function(obj, index) {
          //遍历 删除数组对应的id
          if (arr.findIndex(item => item == obj) !== -1) {
            arr.splice(arr.findIndex(item => item == obj), 1);
          }
        });
      }
      this.curdefult = arr; //设定v-model的值为改变后数组
      this.$emit("curcheck", arr); //向上提交
    },
    //遍历children返回id
    maparr(data) {
      let childprops = this.childprops;
      let newarr = [];
      function searchs(data) {
        data.map(item => {
          newarr.push(item.id);
          if (
            item[childprops.children] &&
            item[childprops.children].length > 0
          ) {
            searchs(item[childprops.children]);
          }
        });
      }
      searchs(data);

      return newarr;
    },
    //遍历children返回name文字
    mapname(data) {
      let childprops = this.childprops;
      let newarr = [];
      function searchs(data) {
        data.map(item => {
          newarr.push(item[childprops.name]);
          if (
            item[childprops.children] &&
            item[childprops.children].length > 0
          ) {
            searchs(item[childprops.children]);
          }
        });
      }
      searchs(data);

      return newarr;
    },
    //去重合并
    uq(array, array1) {
      //将array数组转换成set对象
      let setObj = new Set(array);
      //循环数组array1，并将值通过add插入set对象中,此时重复数据并不会插入其中
      for (let i = 0; i < array1.length; i++) {
        setObj.add(array1[i]);
      }
      //使用Array.from()方法将set对象转换成数组，并使用sort()方法排序 .sort()
      return Array.from(setObj);
    },
    //去重合并 不排序
    nameuq(array, array1) {
      //将array数组转换成set对象
      let setObj = new Set(array);
      //循环数组array1，并将值通过add插入set对象中,此时重复数据并不会插入其中
      for (let i = 0; i < array1.length; i++) {
        setObj.add(array1[i]);
      }
      //使用Array.from()方法将set对象转换成数组，并使用sort()方法排序
      return Array.from(setObj);
    },
    //选中项默认展开
    changeShow(val) {
      //types 1是多选 2 单选

      let childprops = this.childprops;
      let curata = this.datas[childprops.children];
      //console.log(curata)
      if (val instanceof Array) {
        if (curata instanceof Array) {
          //有子级
          for (let i = 0; i < val.length; i++) {
            const element = val[i];
            for (let j = 0; j < curata.length; j++) {
              const obj = curata[j].id;
              if (element == obj) {
                this.$set(this.datas, "showChild", true);
                this.$emit("showid", val);
              }
            }
          }
        } else {
        }
      } else {
        if (val.parentId == this.datas.id) {
          this.$set(this.datas, "showChild", true);
          this.$emit("showid", this.datas);
        }
      }
    },
    //当前选中
    curCheck(val) {
      const me = this;
      let childprops = this.childprops;
      if (this.multiple) {
        //多选
        let arr = val;
        //this.changeShow(val);
        this.curdefult = val;

        let have = false;
        if (me.datas[childprops.children] instanceof Array) {
          //如果有子集 则把子集的项取消选择 在数组删除对应的项
          let haveid = this.maparr(me.datas[childprops.children]); //获取所有子集的id
          //  if (this.assTrue == 2) {
          // if(arr.findIndex(item => item == me.datas.id) == -1){
          //   let len = 0;
          //   haveid.map(function(obj, index) {
          //     for (let i = 0; i < arr.length; i++) {
          //       if(obj == arr[i]){
          //         len++
          //       }
                
          //     }
          //     // if (arr.findIndex(item => item == obj) !== -1) {
          //     //   arr.splice(arr.findIndex(item => item == obj), 1);
          //     // }
          //   });
          //   console.log(len)
          // }
          // }
           
            arr.map(function(ele, ins) {
              haveid.map(dsd => {
                if (ele == dsd) {
                  have = true;
                }
              });
            });
          if (this.assTrue == 1) {
            if (!have) {
              val.map(function(ele, ins) {
                if (ele == me.datas.id) {
                  val.splice(ins, 1);
                }
              });
            }
          } 
          // else if(this.assTrue == 2) {
          //   if (have) {
          //     val.map(function(ele, ins) {
          //       if (ele == haveid[0]) {
          //         val.splice(ins, 0,me.datas.id);
          //       }
          //     });
          //   }
          // }
        }
        this.$emit("curcheck", val);
      } else {
        this.onedefault = val.id;
        //this.changeShow(val);
        this.$emit("curcheck", val);
      }
    },
    //当前选中的name
    namearrd(val) {
      let arr = this.namearrsto;
      if (val.length < arr.length) {
        this.namearrsto = val;
        this.$emit("namearr", val);
      } else {
        arr = this.nameuq(arr, val);
        this.$emit("namearr", arr);
      }
    }
  }
};
</script>
<style lang="scss" scoped>
.z-tree {
  width: 100%;
  .z-tree-node {
    overflow: hidden;
    padding-right: 0px;
    // padding:0 5px;
    .z-tree-content {
      font-size: 13px;
      color: #606266;
      cursor: pointer;
      padding: 0 5px;
      height: 28px;
      line-height: 28px;
      position: relative;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      .z-tree-icon {
        font-size: 14px;
        font-style: inherit;
        cursor: default;
        padding: 0 8px;
        height: 28px;
        line-height: 28px;
      }
      .z-tree-node-text {
        padding-left: 0px;
        line-height: 28px;
        display: inline;
      }
    }

    .z-tree-content:hover {
      background-color: #f5f7fa;
    }
    .active {
      color: #409eff;
      font-weight: 700;
      background-color: #f5f7fa;
      .z-tree-icon {
        color: #606266;
        font-weight: normal;
      }
    }
    .active:hover {
      background-color: #f5f7fa;
    }
    .notallow {
      cursor: not-allowed;
    }
  }
}
.z-none {
  color: transparent;
  width: 30px;
  height: 0px;
  display: inline-block;
}
.z-mulbox {
  display: inline-block;
  position: relative;
}
.z-mask {
  position: absolute;
  z-index: 2;
  width: 100%;
  height: 28px;
}
.z-check {
  position: relative;
  z-index: 1;
}
.z-check.is-checked .el-checkbox__label {
  color: #409eff !important;
}
.z-tree-node-children {
  transition: height ease 0.5s;
  display: block;
  overflow: hidden;
}
</style>
